package de.ifi.lmu.snitzelhunt.util;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;

import android.os.AsyncTask;
import android.util.Log;
import de.ifi.lmu.snitzelhunt.util.basics.Ranking;
import de.ifi.lmu.snitzelhunt.util.basics.RankingContainer;
import de.ifi.lmu.snitzelhunt.util.responses.AsyncServer_Ranking_CreateResponse;
import de.ifi.lmu.snitzelhunt.util.responses.AsyncServer_Ranking_ReadResponse;
import de.ifi.lmu.snitzelhunt.util.responses.AsyncServer_Route_CreateResponse;
import de.ifi.lmu.snitzelhunt.util.responses.Server_Ranking_CreateResponse;
import de.ifi.lmu.snitzelhunt.util.responses.Server_Ranking_ReadResponse;

/**
 * Utilities for handling operations on the remote mySQL database via HTTP POST
 * requests
 * 
 * @author jaschkowitz
 * 
 */
public class RankingServerUtility {

	/**
	 * Method to download a Ranking from the mySQL Server. An AsyncTask is used
	 * to start a new thread outside of the UI Thread.
	 * {@link AsyncServer_Ranking_ReadResponse} target is used for the caller to
	 * get the response from the Server
	 * 
	 * @param globalID
	 * @param target
	 */
	public void readRanking(long globalID, AsyncServer_Ranking_ReadResponse target) {
		new ReadRankingTask(target).execute(globalID);
	}

	/**
	 * Method to upload a Ranking to the mySQL Server. An AsyncTask is used to
	 * start a new thread outside of the UI Thread.
	 * {@link AsyncServer_Route_CreateResponse} target is used for the caller to
	 * get the response from the Server
	 * 
	 * 
	 * @param r
	 * @param target
	 */
	public void createRanking(Ranking r,
			AsyncServer_Ranking_CreateResponse target) {
		new UploadRankingTask(target).execute(r);
	}

	/**
	 * AsyncTask to download a Ranking from the remote mySQL Database.
	 * 
	 * @author jaschkowitz
	 * 
	 */
	private class ReadRankingTask extends
			AsyncTask<Long, Void, Server_Ranking_ReadResponse> {
		private AsyncServer_Ranking_ReadResponse target;

		private ReadRankingTask(AsyncServer_Ranking_ReadResponse targetAct) {
			super();
			target = targetAct;
		}

		@Override
		protected Server_Ranking_ReadResponse doInBackground(Long... globalID) {
			InputStream connIS = null;
			OutputStream connOS = null;
			HttpURLConnection conn = null;
			Server_Ranking_ReadResponse resp = new Server_Ranking_ReadResponse();

			try {
				// Setup for the Connection
				URL url = new URL(
						"http://141.84.213.225:8080/MSP/downloadRanking");
				conn = ConnectionHelper.setupHttpConnection(url);

				// Connect
				conn.connect();

				// post global RouteID to Server
				connOS = conn.getOutputStream();
				String json = GSonUtility.serializeLong(globalID[0]);
				connOS = conn.getOutputStream();
				ConnectionHelper.writeString(connOS, json);
				Log.i("snitzelhunt util", "POST read Route to URL : " + url);
				Log.i("snitzelhunt util",
						"Response Code : " + conn.getResponseCode());

				// get Server Response
				if (conn.getResponseCode() == 200) { // succesful
					connIS = conn.getInputStream();
					String recv = ConnectionHelper.readResponse(connIS);

					RankingContainer recC = GSonUtility
							.deserializeRankingContainer(recv);
					resp.setRankCont(recC);
				}
				resp.setHttpStatus(conn.getResponseCode());
				return resp;
			} catch (IOException e) {
				ConnectionHelper.handleIOException(e);
			} finally {
				ConnectionHelper.cleanConnection(connIS, connOS, conn);
			}

			resp.setHttpStatus(-1);
			return resp;
		}

		protected void onPostExecute(Server_Ranking_ReadResponse result) {
			target.processServer_Ranking_ReadResponse(result);
		}
	}

	/**
	 * AsyncTask to upload a Ranking to the remote mySQL Database.
	 * 
	 * @author jaschkowitz
	 * 
	 */
	private class UploadRankingTask extends
			AsyncTask<Ranking, Void, Server_Ranking_CreateResponse> {
		private AsyncServer_Ranking_CreateResponse target;

		private UploadRankingTask(AsyncServer_Ranking_CreateResponse targetAct) {
			super();
			target = targetAct;
		}

		@Override
		protected Server_Ranking_CreateResponse doInBackground(
				Ranking... ranking) {
			InputStream connIS = null;
			OutputStream connOS = null;
			HttpURLConnection conn = null;
			Server_Ranking_CreateResponse resp = new Server_Ranking_CreateResponse();

			try {
				// Setup for the Connection
				URL url = new URL(
						"http://141.84.213.225:8080/MSP/uploadRanking");
				conn = ConnectionHelper.setupHttpConnection(url);

				// Connect
				conn.connect();

				// post Ranking to Server
				String json = GSonUtility.serializeRanking(ranking[0]);
				connOS = conn.getOutputStream();
				ConnectionHelper.writeString(connOS, json);
				Log.i("snitzelhunt util", "POST upload Ranking to URL : " + url);
				Log.i("snitzelhunt util",
						"Response Code : " + conn.getResponseCode());

				resp.setHttpStatus(conn.getResponseCode());
				return resp;
			} catch (IOException e) {
				ConnectionHelper.handleIOException(e);
			} finally {
				ConnectionHelper.cleanConnection(connIS, connOS, conn);
			}
			resp.setHttpStatus(-1);
			return resp;
		}

		protected void onPostExecute(Server_Ranking_CreateResponse result) {
			target.processServer_Ranking_Create(result);
		}
	}
}
